home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / midas060 / src / sb.asm < prev    next >
Encoding:
Assembly Source File  |  1997-01-16  |  34.2 KB  |  1,479 lines

  1. ;*    SB.ASM
  2. ;*
  3. ;* Sound Blaster series Sound Device
  4. ;*
  5. ;* $Id: sb.asm,v 1.5 1997/01/16 18:41:59 pekangas Exp $
  6. ;*
  7. ;* Copyright 1996,1997 Housemarque Inc.
  8. ;*
  9. ;* This file is part of the MIDAS Sound System, and may only be
  10. ;* used, modified and distributed under the terms of the MIDAS
  11. ;* Sound System license, LICENSE.TXT. By continuing to use,
  12. ;* modify or distribute this file you indicate that you have
  13. ;* read the license and understand and accept it fully.
  14. ;*
  15.  
  16.  
  17.  
  18. IDEAL
  19. P386
  20. JUMPS
  21.  
  22. INCLUDE "lang.inc"
  23. INCLUDE "errors.inc"
  24. INCLUDE "sdevice.inc"
  25. INCLUDE "dsm.inc"
  26. INCLUDE "dma.inc"
  27. INCLUDE "mixsd.inc"
  28. INCLUDE "mutils.inc"
  29.  
  30.  
  31. SB_RESETDELAY = 64      ; Delay for SB reset. According to SDK 8 should be
  32.                         ; enough but doesn't seem so on my P90 (PK)
  33.  
  34.  
  35.  
  36. ;/***************************************************************************\
  37. ;*     enum sbFunctIDs
  38. ;*     ----------------
  39. ;* Description:  ID numbers for SB Sound Device functions
  40. ;\***************************************************************************/
  41.  
  42. enum    sbFunctIDs \
  43.     ID_sbDetect = ID_sb, \
  44.     ID_sbInit, \
  45.         ID_sbClose
  46.  
  47.  
  48.  
  49. ;/***************************************************************************\
  50. ;*    ENUM sbCardTypes
  51. ;*    ----------------
  52. ;* Description: Sound Card type number for SB Sound Device
  53. ;\***************************************************************************/
  54.  
  55. ENUM    sbCardTypes \
  56.     sbAutoType = 0, \        ; autodetect card type
  57.     sb10, \             ; Sound Blaster 1.0 (DSP v1.xx)
  58.     sb15, \             ; Sound Blaster 1.5 (DSP v2.00)
  59.     sb20, \             ; Sound Blaster 2.0 (DSP v2.01)
  60.     sbPro, \            ; Sound Blaster Pro (DSP v3.xx)
  61.     sb16                ; Sound Blaster 16 (DSP v4.00+)
  62.  
  63.  
  64.  
  65. DATASEG
  66.  
  67. D_farptr oldIRQ                         ; old IRQ vector
  68. D_int   sb22C                           ; SB DSP data port (2xCh)
  69. D_int   sbTimeConstant                  ; SB Transfer Time Constant
  70. D_int   sbRate                          ; SB actual playing rate
  71. D_int   sbVersion                       ; DSP version number
  72. D_int   sbMode                          ; actual output mode
  73. D_int   sbInterrupt                     ; IRQ interrupt number
  74. D_int   sbBlockLength                   ; DSP playing block length
  75. D_int   sbStereoOK                      ; flag used by sbSetStereo()
  76.  
  77. sbStereoDMABuffer  dmaBuffer ?          ; dummy DMA buffer used to play one
  78.                                         ; byte with DMA before starting with
  79.                                         ; SB Pro cards to get left and right
  80.                                         ; channel the right way
  81.  
  82. convBuffer      DB      4 DUP (?)       ; string to number conversion buffer
  83. oldIRQMask      DB      ?               ; old IRQ mask
  84. sbOutputFilter  DB      ?               ; initial output filter status
  85.  
  86.  
  87.  
  88. IFDEF __PASCAL__
  89. EXTRN   SB : SoundDevice                ; Sound Device for Pascal version
  90. ENDIF
  91.  
  92.  
  93.  
  94.  
  95. IDATASEG
  96.  
  97.  
  98. SBCONFIGBITS = sdUsePort or sdUseIRQ or sdUseDMA or sdUseMixRate or \
  99.                sdUseOutputMode or sdUseDSM
  100. SBMODEBITS = sdMono or sdStereo or sd8bit or sd16bit
  101.  
  102. ; If compiling for Pascal, Sound Device name is sbSD, from which the data
  103. ; will be copied to Sound Device SB, defined in Pascal.
  104.  
  105. IFDEF   __PASCAL__
  106. SDNAM           equ     sbSD
  107. ELSE
  108. SDNAM           equ     SB
  109. ENDIF
  110.  
  111. GLOBAL  SDNAM : SoundDevice
  112.  
  113. SDNAM   SoundDevice     < \
  114.  0,\
  115.  SBCONFIGBITS,\
  116.  220h, 7, 1,\
  117.  sbAutoType, 5,\
  118.  SBMODEBITS,\
  119.  ptr_to sbSDName,\
  120.  ptr_to sbCardNames,\
  121.  4, ptr_to sbPortAddresses,\
  122.  ptr_to sbDetect,\
  123.  ptr_to sbInit,\
  124.  ptr_to sbClose,\
  125.  ptr_to dsmGetMixRate,\
  126.  ptr_to mixsdGetMode,\
  127.  ptr_to mixsdOpenChannels,\
  128.  ptr_to dsmCloseChannels,\
  129.  ptr_to dsmClearChannels,\
  130.  ptr_to dsmMute,\
  131.  ptr_to dsmPause,\
  132.  ptr_to dsmSetMasterVolume,\
  133.  ptr_to dsmGetMasterVolume,\
  134.  ptr_to mixsdSetAmplification,\
  135.  ptr_to mixsdGetAmplification,\
  136.  ptr_to dsmPlaySound,\
  137.  ptr_to dsmReleaseSound\
  138.  ptr_to dsmStopSound,\
  139.  ptr_to dsmSetRate,\
  140.  ptr_to dsmGetRate,\
  141.  ptr_to dsmSetVolume,\
  142.  ptr_to dsmGetVolume,\
  143.  ptr_to dsmSetSample,\
  144.  ptr_to dsmGetSample,\
  145.  ptr_to dsmSetPosition,\
  146.  ptr_to dsmGetPosition,\
  147.  ptr_to dsmGetDirection,\
  148.  ptr_to dsmSetPanning,\
  149.  ptr_to dsmGetPanning,\
  150.  ptr_to dsmMuteChannel,\
  151.  ptr_to dsmAddSample,\
  152.  ptr_to dsmRemoveSample,\
  153.  ptr_to mixsdSetUpdRate,\
  154.  ptr_to mixsdStartPlay,\
  155.  ptr_to mixsdPlay >
  156.  
  157. sbSDName        DB      "Sound Blaster series Sound Device v2.21",0
  158.  
  159.                 ; *!!*
  160. sbCardNames     DD      ptr_to sb10Name
  161.                 DD      ptr_to sb15Name
  162.                 DD      ptr_to sb20Name
  163.                 DD      ptr_to sbProName
  164.                 DD      ptr_to sb16Name
  165.  
  166. sb10Name    DB    "Sound Blaster 1.0 or clone (DSP v1.xx)", 0
  167. sb15Name    DB    "Sound Blaster 1.5 (DSP v2.00)", 0
  168. sb20Name    DB    "Sound Blaster 2.0 (DSP v2.01)", 0
  169. sbProName    DB    "Sound Blaster Pro (DSP v3.xx)", 0
  170. sb16Name    DB    "Sound Blaster 16 (DSP v4.00+)", 0
  171.  
  172. IFDEF __16__
  173. sbPortAddresses DW    210h, 220h, 230h, 240h, 250h, 260h
  174. ELSE
  175. sbPortAddresses DD      210h, 220h, 230h, 240h, 250h, 260h
  176. ENDIF
  177.  
  178. blasterStr    DB    "BLASTER", 0
  179.  
  180.  
  181.  
  182. CODESEG
  183.  
  184.  
  185.  
  186. PUBLIC    sbDetect
  187. PUBLIC    sbInit
  188. PUBLIC    sbClose
  189.  
  190.  
  191.  
  192.  
  193. ;/***************************************************************************\
  194. ;*
  195. ;* Function:    sbWait
  196. ;*
  197. ;* Description: Waits until data can be written to the DSP command/data port
  198. ;*        2xCh
  199. ;*
  200. ;* Returns:     MIDAS error code
  201. ;*
  202. ;* Destroys:    _ax, _cx, _dx. _dx now contains the DSP command/data port
  203. ;*              value, 2xCh.
  204. ;*
  205. ;\***************************************************************************/
  206.  
  207. PROC NOLANGUAGE sbWait    NEAR
  208.  
  209.         mov     _dx,[sb22C]
  210.         mov     _cx,0FFFFh
  211.  
  212. @@wait:
  213.     in    al,dx            ; read port 22Ch
  214.     test    al,al            ; is bit 7 set?
  215.     jns    @@ok            ; if not, DSP is ready
  216.     loop    @@wait            ; read maximum of 0FFFFh times
  217.  
  218.  
  219.     ; The bit is still set after 0FFFFh reads, so apparently the DSP
  220.     ; is for some reason locked up. Return error.
  221.  
  222.         mov     _ax,errSDFailure        ; Sound Device hardware failure
  223.     jmp    @@done
  224.  
  225. @@ok:
  226.         xor     _ax,_ax
  227.  
  228. @@done:
  229.     ret
  230. ENDP
  231.  
  232.  
  233.  
  234.  
  235. ;/***************************************************************************\
  236. ;*
  237. ;* Macro:    SBCMD
  238. ;*
  239. ;* Description: Writes a command to SB's DSP. Jumps to label @@err if an
  240. ;*        error occurs, with the error code in ax
  241. ;*
  242. ;* Input:    command     command
  243. ;*
  244. ;* Destroys:    see function sbCommand
  245. ;*
  246. ;\***************************************************************************/
  247.  
  248. MACRO    SBCMD    command
  249.     mov    bl,command
  250.     call    sbCommand
  251.         test    _ax,_ax
  252.     jnz    @@err
  253. ENDM
  254.  
  255.  
  256.  
  257.  
  258. ;/***************************************************************************\
  259. ;*
  260. ;* Function:    sbCommand
  261. ;*
  262. ;* Description: Writes a command to SB's DSP
  263. ;*
  264. ;* Input:    bl    command
  265. ;*
  266. ;* Returns:     MIDAS error code in _ax
  267. ;*
  268. ;* Destroys:    _ax, _dx, _cx
  269. ;*
  270. ;\***************************************************************************/
  271.  
  272. PROC NOLANGUAGE sbCommand    NEAR
  273.  
  274.     call    sbWait            ; wait until data or command can be
  275.         test    _ax,_ax                 ; written to the DSP
  276.     jnz    @@done
  277.  
  278.     mov    al,bl            ; write the command
  279.     out    dx,al
  280.  
  281.         xor     _ax,_ax
  282.  
  283. @@done:
  284.     ret
  285. ENDP
  286.  
  287.  
  288.  
  289.  
  290. ;/***************************************************************************\
  291. ;*
  292. ;* Function:    sbRead
  293. ;*
  294. ;* Description: Reads a byte from the DSP data port
  295. ;*
  296. ;* Returns:    bl        byte read
  297. ;*              _ax             MIDAS error copde
  298. ;*
  299. ;* Destroys:    _ax, _cx, _dx
  300. ;*
  301. ;\***************************************************************************/
  302.  
  303. PROC NOLANGUAGE sbRead        NEAR
  304.  
  305.         mov     _dx,[SB.port]
  306.         add     _dx,0Eh                 ; dx = 2xEh = SB DSP Data Available
  307.         mov     _cx,0FFFFh              ; port
  308. @@wait:
  309.     in    al,dx
  310.     test    al,al            ; wait until bit 7 is set
  311.     js    @@dok
  312.     loop    @@wait
  313.  
  314.     ; Read port 2xEh 65535 time and bit 7 is still zero - failure
  315.         mov     _ax,errSDFailure
  316.     jmp    @@done
  317.  
  318. @@dok:  add     _dx,0Ah-0Eh             ; dx = 2xAh = SB DSP Data port
  319.     in    al,dx            ; read data from port
  320.     mov    bl,al            ; and store it in bl
  321.  
  322.         xor     _ax,_ax                 ; success
  323.  
  324. @@done:
  325.     ret
  326. ENDP
  327.  
  328.  
  329.  
  330.  
  331. ;/***************************************************************************\
  332. ;*
  333. ;* Function:    sbReset
  334. ;*
  335. ;* Description: Resets the Sound Blaster DSP
  336. ;*
  337. ;\***************************************************************************/
  338.  
  339. PROC    sbReset         NEAR
  340.  
  341.         mov     _dx,[SB.port]
  342.         add     _dx,6
  343.     mov    al,1            ; reset SB DSP by first writing 1 to
  344.     out    dx,al            ; port 2x6h
  345.         mov     _cx,SB_RESETDELAY
  346. @@delay:
  347.     in    al,dx            ; wait for a while (3 usecs)
  348.     loop    @@delay
  349.     xor    al,al            ; and write 0 to port 2x6h
  350.         out     dx,al
  351.  
  352.         mov     _dx,[SB.port]
  353.         add     _dx,0Eh                 ; SB data available port 2xEh
  354.         mov     _cx,1000
  355.  
  356. @@wd1:    in    al,dx
  357.     test    al,al
  358.     js    @@ok1            ; wait until bit 7 (data available)
  359.     loop    @@wd1            ; is 1 or 1000 times
  360.         jmp     @@err                   ; no data - no SB
  361.  
  362. @@ok1:  add     _dx,0Ah-0Eh             ; read data port (2xAh)
  363.         mov     _cx,1000
  364.  
  365. @@wd2:    in    al,dx
  366.     cmp    al,0AAh         ; wait until data is 0AAh or 1000
  367.     je    @@sbok            ; times
  368.     loop    @@wd2
  369.         jmp     @@err                   ; no 0AAh - no SB
  370.  
  371. @@sbok:
  372.         xor     _ax,_ax                 ; SB resetted succesfully
  373.         jmp     @@done
  374.  
  375. @@err:
  376.         mov     _ax,errSDFailure
  377.  
  378. @@done:
  379.         ret
  380. ENDP
  381.  
  382.  
  383.  
  384.  
  385. ;/***************************************************************************\
  386. ;*
  387. ;* Function:    sbGetVersion
  388. ;*
  389. ;* Description: Get Sound Blaster DSP version and set up SB.cardType,
  390. ;*              sbVersion and SB.modes accordingly
  391. ;*
  392. ;\***************************************************************************/
  393.  
  394. PROC NOLANGUAGE sbGetVersion    NEAR
  395.  
  396.     SBCMD    0E1h            ; Get DSP version number
  397.     call    sbRead            ; read version high byte
  398.         test    _ax,_ax
  399.     jnz    @@err
  400.     mov    bh,bl
  401.     call    sbRead            ; read version low byte
  402.         test    _ax,_ax
  403.     jnz    @@err
  404.         mov     [sbVersion],_bx         ; store version number
  405.  
  406.         cmp     _bx,200h                ; DSP version < 2.00?
  407.     jb    @@sb10            ; if yes, SB version 1.0
  408.         cmp     _bx,200h                ; DSP version 2.00?
  409.     je    @@sb15            ; if yes, SB version 1.5
  410.         cmp     _bx,300h                ; DSP version < 3.00?
  411.     jb    @@sb20            ; if yes, SB version 2.0
  412.         cmp     _bx,400h                ; DSP version < 4.00?
  413.     jb    @@sbPro         ; if yes, SB Pro
  414.  
  415.     ; DSP version >= 4.00 - Sound Blaster 16
  416.     mov    [SB.cardType],sb16
  417.         mov     [SB.modes],sdMono or sdStereo or sd8bit or sd16bit
  418.         jmp     @@ok
  419.  
  420. @@sb10:
  421.     ; SB version 1.0
  422.     mov    [SB.cardType],sb10
  423.         mov     [SB.modes],sdMono or sd8bit
  424.     jmp    @@ok
  425.  
  426. @@sb15:
  427.     ; SB version 1.5
  428.     mov    [SB.cardType],sb15
  429.         mov     [SB.modes],sdMono or sd8bit
  430.     jmp    @@ok
  431.  
  432. @@sb20:
  433.     ; SB version 2.0
  434.     mov    [SB.cardType],sb20
  435.         mov     [SB.modes],sdMono or sd8bit
  436.     jmp    @@ok
  437.  
  438. @@sbPro:
  439.     ; SB Pro
  440.     mov    [SB.cardType],sbPro
  441.         mov     [SB.modes],sdMono or sdStereo or sd8bit
  442.  
  443. @@ok:
  444.         xor     _ax,_ax
  445.  
  446. @@err:
  447.     ret
  448. ENDP
  449.  
  450.  
  451.  
  452. ;/***************************************************************************\
  453. ;*
  454. ;* Function:    int sbDetect(int *result);
  455. ;*
  456. ;* Description: Detects Sound Blaster soundcard
  457. ;*
  458. ;* Returns:    MIDAS error code.
  459. ;*        1 stored to *result if SB was detected, 0 if not.
  460. ;*
  461. ;\***************************************************************************/
  462.  
  463. PROC    sbDetect        _funct          result : _ptr
  464. USES    _si,_di,_bx
  465. LOCAL   port : _int, IRQ : _int, DMA : _int, highDMA : _int
  466.  
  467.     ; Search for "BLASTER" environment string:
  468. IFDEF __16__
  469.     call    mGetEnv LANG, seg blasterStr offset blasterStr
  470.         mov     bx,dx                   ; was "BLASTER" environment found?
  471.     or    bx,ax            ; if not, no SB
  472.     jz    @@nosb
  473.  
  474.     mov    es,dx            ; point es:si to environment
  475.     mov    si,ax            ; string
  476.  
  477. ELSE
  478.         call    mGetEnv LANG, offset blasterStr
  479.         test    eax,eax                 ; was "BLASTER" environment found?
  480.         jz      @@nosb                  ; if not, no SB
  481.     jz    @@nosb
  482.  
  483.         mov     esi,eax                 ; point _essi to environment string
  484.  
  485. ENDIF
  486.         mov     [port],-1               ; no port found
  487.     mov    [IRQ],-1        ; no IRQ found
  488.     mov    [DMA],-1        ; no DMA found
  489.     mov    [highDMA],-1        ; no High DMA found
  490.  
  491. @@envloop:
  492.         mov     al,[_essi]              ; get character from string
  493.         inc     _si
  494.     test    al,al            ; end of string?
  495.     jz    @@strend
  496.  
  497.     and    al,not 20h        ; convert to uppercase if a letter
  498.  
  499.     cmp    al,'A'                  ; Axxx - port address
  500.     je    @@port
  501.  
  502.     cmp    al,'I'                  ; Ix - IRQ number
  503.     je    @@irq
  504.  
  505.     cmp    al,'D'                  ; Dx - DMA channel number
  506.     je    @@dma
  507.  
  508.     cmp    al,'H'                  ; Hx - High DMA channel number
  509.     je    @@highdma
  510.  
  511.     jmp    @@envloop
  512.  
  513.  
  514. @@port:
  515.     ; port - the following characters up to next space or \0, maximum
  516.     ; 3, are the I/O port number in hexadecimal
  517.  
  518.         mov     _cx,4
  519.         mov     _di,offset convBuffer
  520.  
  521. @@ploop:
  522.         mov     al,[_essi]
  523.         inc     _si
  524.     cmp    al,' '
  525.     je    @@port1
  526.     test    al,al
  527.     jz    @@port1
  528.         mov     [_di],al                ; copy port number to conversion
  529.         inc     _di                     ; buffer
  530.     loop    @@ploop         ; max 3 characters
  531.  
  532.     jmp    @@nosb            ; over 3 characters - bad environment
  533.  
  534. @@port1:
  535.         mov     [byte _di],0            ; append terminating zero
  536.  
  537.     ; convert hex string to number:
  538.     push    es
  539. IFDEF __16__
  540.     call    mHex2Long LANG, seg convBuffer offset convBuffer
  541. ELSE
  542.         call    mHex2Long LANG, offset convBuffer
  543. ENDIF
  544.     pop    es
  545.         cmp     _ax,-1
  546.     je    @@nosb
  547.  
  548.         mov     [port],_ax
  549.     jmp    @@envloop
  550.  
  551.  
  552. @@irq:
  553.     ; IRQ - the following characters up to next space or \0, maximum
  554.     ; 2, are the IRQ number in decimal
  555.  
  556.         xor     _ax,_ax
  557.         mov     al,[_essi]              ; get first character
  558.         inc     _si
  559.     cmp    al,'0'                  ; below '0'?
  560.     jb    @@nosb            ; if is, bad environment
  561.     sub    al,'0'
  562.  
  563.         xor     _bx,_bx
  564.         mov     bl,[_essi]              ; next character
  565.     cmp    bl,' '                  ; space?
  566.     je    @@irq1
  567.     test    bl,bl            ; terminating zero?
  568.     jz    @@irq1
  569.     cmp    bl,'0'                  ; below '0'?
  570.     jb    @@nosb            ; if is, bad environment
  571.         sub     bl,'0'
  572.         imul    _ax,_ax,10              ; IRQ = 10*first + second
  573.         add     _ax,_bx
  574.  
  575. @@irq1:
  576.         mov     [IRQ],_ax
  577.     jmp    @@envloop
  578.  
  579.  
  580. @@dma:
  581.     ; DMA - the following character is the DMA channel number
  582.         xor     _ax,_ax
  583.         mov     al,[_essi]              ; get first character
  584.         inc     _si
  585.     cmp    al,'0'                  ; below '0'?
  586.     jb    @@nosb            ; if is, bad environment
  587.     sub    al,'0'
  588.         mov     [DMA],_ax
  589.     jmp    @@envloop
  590.  
  591.  
  592. @@highdma:
  593.     ; High DMA - the following character is the High DMA channel number
  594.         xor     _ax,_ax
  595.         mov     al,[_essi]              ; get first character
  596.         inc     _si
  597.     cmp    al,'0'                  ; below '0'?
  598.     jb    @@nosb            ; if is, bad environment
  599.     sub    al,'0'
  600.         mov     [highDMA],_ax
  601.     jmp    @@envloop
  602.  
  603.  
  604. @@strend:
  605.     ; End of environment string. If port, IRQ or DMA value was not found,
  606.     ; the environment string is bad
  607.     cmp    [port],-1
  608.     je    @@nosb
  609.     cmp    [IRQ],-1
  610.     je    @@nosb
  611.  
  612.     cmp    [highDMA],-1        ; was high DMA channel number found?
  613.     jne    @@high1
  614.  
  615.     cmp    [DMA],-1        ; no, use normal DMA
  616.     je    @@nosb
  617.     jmp    @@set
  618.  
  619. @@high1:
  620.     ; High DMA channel number was found - use it as DMA channel
  621.         mov     _ax,[highDMA]
  622.         mov     [DMA],_ax
  623.  
  624. @@set:
  625.     ; Set detected values to card structure:
  626.         mov     _ax,[port]
  627.         mov     [SB.port],_ax
  628.         add     _ax,0Ch
  629.         mov     [sb22C],_ax
  630.         mov     _ax,[IRQ]
  631.         mov     [SB.IRQ],_ax
  632.         mov     _ax,[DMA]
  633.         mov     [SB.DMA],_ax
  634.  
  635.         call    sbReset                 ; reset the DSP
  636.         test    _ax,_ax
  637.         jnz     @@err
  638.  
  639.         cmp     [SB.cardType],sbAutoType        ; has a card type been set?
  640.         jne     @@cardtypeset                   ; if not, detect it
  641.  
  642.         call    sbGetVersion
  643.         test    _ax,_ax
  644.         jnz     @@err
  645.  
  646. @@cardtypeset:
  647.         LOADPTR es,_bx,[result]
  648.         mov     [_int _esbx],1          ; Sound Blaster was detected
  649.         xor     _ax,_ax
  650.     jmp    @@done
  651.  
  652. @@nosb:
  653.         LOADPTR es,_bx,[result]
  654.         mov     [_int _esbx],0          ; Sound Blaster not detected
  655.         xor     _ax,_ax
  656.     jmp    @@done
  657.  
  658. @@err:
  659.     ERROR    ID_sbDetect
  660.  
  661. @@done:
  662.     ret
  663. ENDP
  664.  
  665.  
  666.  
  667.  
  668. ;/***************************************************************************\
  669. ;*
  670. ;* Function:    int sbInit(unsigned mixRate, unsigned mode);
  671. ;*
  672. ;* Description: Initializes Sound Blaster series Sound Device
  673. ;*
  674. ;* Input:       unsigned mixRate        mixing rate
  675. ;*              unsigned mode           output mode (see enum sdMode)
  676. ;*
  677. ;* Returns:    MIDAS error code
  678. ;*
  679. ;\***************************************************************************/
  680.  
  681. PROC    sbInit          _funct  mixRate : _int, mode : _int
  682. USES    _bx
  683.  
  684.         mov     _ax,[SB.port]
  685.         add     _ax,0Ch                 ; set sb22C variable to real SB DSP
  686.         mov     [sb22C],_ax             ; command port
  687.  
  688.         call    sbReset                 ; reset the DSP
  689.         jnz     @@err
  690.  
  691.         cmp     [SB.cardType],sbAutoType        ; has a card type been set?
  692.     jne    @@typeset
  693.         call    sbGetVersion                    ; if not, detect it
  694.  
  695. @@typeset:
  696.     cmp    [SB.cardType],sb16    ; Sound Blaster 16?
  697.     je    @@modeall        ; if yes, all modes supported
  698.     cmp    [SB.cardType],sbPro    ; Sound Blaster Pro?
  699.     jae    @@modestereo        ; if yes, stereo is supported
  700.  
  701.     ; normal Sound Blaster - only 8-bit mono
  702.     mov    [sbMode],sd8bit or sdMono
  703.     jmp    @@moded
  704.  
  705. @@modestereo:
  706.     ; Sound Blaster Pro - only 8-bit mono or stereo
  707.         mov     _ax,sd8bit              ; 8-bit output
  708.     test    [mode],sdMono        ; is mono mode forced?
  709.     jnz    @@smono
  710.         or      _ax,sdStereo            ; no, use stereo
  711.     jmp    @@sok
  712. @@smono:
  713.         or      _ax,sdMono              ; yes, use mono
  714. @@sok:
  715.         mov     [sbMode],_ax            ; store output mode
  716.     jmp    @@moded
  717.  
  718.  
  719. @@modeall:
  720.     ; Sound Blaster 16 - all output modes
  721.     test    [mode],sd8bit        ; force 8-bit?
  722.     jnz    @@8b
  723.         mov     _ax,sd16bit             ; if not, use 16 bits
  724.     jmp    @@bit
  725. @@8b:   mov     _ax,sd8bit
  726.  
  727. @@bit:    test    [mode],sdMono        ; force mono?
  728.     jnz    @@mono
  729.         or      _ax,sdStereo            ; if not, use stereo
  730.     jmp    @@mst
  731. @@mono: or      _ax,sdMono
  732.  
  733. @@mst:  mov     [sbMode],_ax
  734.  
  735. @@moded:
  736.         mov     _ax,[SB.IRQ]
  737.     cmp    al,7            ; IRQ number > 7 ?
  738.     ja    @@i8
  739.  
  740.     add    al,8            ; no, interrupt number is IRQ+8
  741.     jmp    @@ivect
  742.  
  743. @@i8:    add    al,70h-8        ; yes, interrupt number is IRQ+68h
  744.  
  745. @@ivect:
  746.         mov     [sbInterrupt],_ax       ; save interrupt number
  747.  
  748.         push    es
  749.     mov    ah,35h
  750.     int    21h            ; save old IRQ vector
  751.         mov     [_int oldIRQ],_bx
  752.         mov     [word oldIRQ+INTSIZE],es
  753.         pop     es
  754.  
  755.         mov     _ax,[SB.IRQ]
  756.     cmp    al,7            ; is IRQ > 7 ?
  757.     ja    @@i82
  758.  
  759.     mov    cl,al            ; no
  760.     in    al,21h
  761.         mov     [oldIRQMask],al         ; save old IRQ mask
  762.     mov    bl,not 1
  763.     rol    bl,cl            ; enable SB's IRQ
  764.     and    al,bl
  765.     out    21h,al
  766.     jmp    @@idone
  767.  
  768. @@i82:    mov    cl,al
  769.     sub    cl,8
  770.     in    al,0A1h
  771.         mov     [oldIRQMask],al         ; save old IRQ mask
  772.     mov    bl,not 1
  773.     rol    bl,cl            ; enable SB's IRQ
  774.     and    al,bl
  775.     out    0A1h,al
  776.  
  777. @@idone:
  778.  
  779.     cmp    [SB.cardType],sb16    ; Sound Blaster 16?
  780.     jae    @@userate        ; if so, the sampling rate is directly
  781.                     ; used
  782.  
  783.     cmp    [SB.cardType],sb20    ; Sound Blaster version < 2.0?
  784.     jb    @@limit1        ; if yes, rate limit is 21739Hz
  785.  
  786.     ; Sound Blaster 2.0 or Pro - sampling rate limit is 43478Hz, so the
  787.     ; maximum Time Constant is 233
  788.     mov    ecx,233
  789.     jmp    @@timeconstant
  790.  
  791. @@limit1:
  792.     ; Sound Blaster 1.0 or 1.5 - sampling rate limit is 21739Hz, making
  793.     ; the maximum Time Constant 210
  794.     mov    ecx,210
  795.  
  796. @@timeconstant:
  797.     ; Calculate the Transfer Time Constant
  798. IFDEF __16__
  799.         xor     ebx,ebx
  800. ENDIF
  801.         mov     _bx,[mixRate]
  802.     test    [sbMode],sdStereo    ; use stereo?
  803.     jz    @@nostt         ; if yes, multiply rate with 2 when
  804.     shl    ebx,1            ; calculating Time Constant
  805.  
  806. @@nostt:
  807.     mov    eax,1000000        ; eax = Time Constant =
  808.         xor     edx,edx                 ; 256 - (1000000 / rate)
  809.     div    ebx
  810.     neg    eax
  811.     add    eax,256
  812.  
  813.     test    eax,eax
  814.     jns    @@non1            ; Time Constant must be nonnegative
  815.     xor    eax,eax
  816.  
  817. @@non1: cmp    eax,ecx         ; ecx is the maximum Time Constant
  818.     jbe    @@noa1
  819.     mov    eax,ecx         ; limit Time Constant to ecx value
  820.  
  821. @@noa1: mov     [sbTimeConstant],_ax    ; store Transfer Time Constant
  822.  
  823.     mov    ebx,256
  824.     sub    ebx,eax
  825.     mov    eax,1000000        ; calculate actual playing rate
  826.         xor     edx,edx                 ; (= 1000000 / (256 - TimeConstant))
  827.     div    ebx
  828.  
  829.     test    [sbMode],sdStereo    ; using stereo?
  830.     jz    @@nostt2
  831.     shr    eax,1            ; divide with 2 to get rate
  832.  
  833. @@nostt2:
  834.         mov     [sbRate],_ax
  835.         jmp     @@initmixsd
  836.  
  837.  
  838. @@userate:
  839.     ; Sound Blaster 16 - output uses the sampling rate directly
  840.         mov     _ax,[mixRate]
  841.         mov     [sbRate],_ax
  842.  
  843.  
  844. @@initmixsd:
  845.         cmp     [SB.cardType],sbPro     ; if playing stereo on SB Pro
  846.     jne    @@dmaok         ; set stereo mode and output one
  847.     test    [sbMode],sdStereo    ; silent byte before starting the
  848.     jz    @@dmaok         ; actual transfer
  849.  
  850.     call    sbSetStereo
  851.         test    _ax,_ax
  852.     jnz    @@err
  853.  
  854. @@dmaok:
  855.         ; Take care of common initialization for all mixing Sound Devices:
  856.         push    es
  857.         call    mixsdInit LANG, [sbRate], [sbMode], [SB.DMA]
  858.         pop     es
  859.         test    _ax,_ax
  860.         jnz     @@err
  861.  
  862.         mov     [sbBlockLength],0FFF0h  ; set DSP block length to 0FFF0h
  863.                     ; samples - autoinit DMA mode takes
  864.                     ; care of wrapping
  865.  
  866.         mov     _bx,[SB.cardType]
  867.         cmp     _bx,sb10                ; Sound Blaster 1.0?
  868.     je    @@v100            ; if is, auto-initialize mode is not
  869.                     ; available
  870.  
  871.     ; set up interrupt service routine for auto-initialize mode:
  872.     push    ds
  873.     mov    ah,25h
  874.         mov     al,[byte sbInterrupt]
  875.         mov     dx,cs
  876.     mov    ds,dx
  877.         mov     _dx,offset sbAutoinitIRQ
  878.     int    21h
  879.     pop    ds
  880.  
  881.         cmp     _bx,sb16                ; Sound Blaster 16?
  882.     je    @@v400            ; if is, use DSP 4.00 playing mode
  883.                     ; for all output modes
  884.  
  885.         cmp     _bx,sb20                ; Sound Blaster 2.0 or Pro?
  886.     jae    @@v201            ; if is, high-speed output is
  887.                     ; available
  888.  
  889.     jmp    @@v200
  890.  
  891.  
  892. @@v100:
  893.     ; Sound Blaster 1.0 - play using mono single-cycle mode
  894.  
  895.     ; set up interrupt service routine for single-cycle mode:
  896.     push    ds
  897.     mov    ah,25h
  898.         mov     al,[byte sbInterrupt]
  899.         mov     dx,cs
  900.     mov    ds,dx
  901.         mov     _dx,offset sbSingleCycleIRQ
  902.     int    21h
  903.     pop    ds
  904.  
  905.     ; start playing:
  906.     call    sbPlayMonoSingleCycle
  907.     jmp    @@playing
  908.  
  909. @@v200:
  910.     ; Sound Blaster 1.5 - play using mono auto-initialize mode
  911.     call    sbPlayMonoAutoinit
  912.     jmp    @@playing
  913.  
  914. @@v201:
  915.     ; Sound Blaster 2.0 or Pro - high-speed output is available
  916.     test    [sbMode],sdStereo    ; use stereo?
  917.     jnz    @@plstereo        ; if yes, play using stereo mode
  918.  
  919.     cmp    [sbRate],22000        ; is sampling rate over 22000Hz?
  920.     ja    @@highspeed        ; if is, use high-speed mode
  921.  
  922.     ; Sound Blaster 2.0 or Pro, mono, rate <= 22000Hz - play using mono
  923.     ; auto-initialize mode
  924.     call    sbPlayMonoAutoinit
  925.     jmp    @@playing
  926.  
  927. @@highspeed:
  928.     ; Sound Blaster 2.0 or Pro, mono, rate > 22000Hz - play using mono
  929.     ; high-speed (auto-initialize) mode
  930.     call    sbPlayMonoHighSpeed
  931.     jmp    @@playing
  932.  
  933. @@plstereo:
  934.     ; Sound Blaster Pro, stereo - play using stereo
  935.     ; high-speed auto-initialize mode
  936.     call    sbPlayStereo
  937.     jmp    @@playing
  938.  
  939. @@v400:
  940.     ; Sound Blaster 16 - use DSP v4.00 auto-initialize mode for all output
  941.     ; modes
  942.     call    sbPlay400
  943.  
  944. @@playing:
  945.         test    _ax,_ax
  946.     jnz    @@err
  947.  
  948.         xor     _ax,_ax                 ; SB succesfully initialized
  949.     jmp    @@done
  950.  
  951. @@sberr:
  952.         mov     _ax,errSDFailure        ; Hardware failure
  953.  
  954. @@err:    ERROR    ID_sbInit
  955.  
  956. @@done:
  957.     ret
  958. ENDP
  959.  
  960.  
  961.  
  962.  
  963. ;/***************************************************************************\
  964. ;*
  965. ;* Function:    sbPlayMonoSingleCycle
  966. ;*
  967. ;* Description: Starts playing the buffer using 8-bit mono Single-Cycle mode
  968. ;*
  969. ;\***************************************************************************/
  970.  
  971. PROC NOLANGUAGE sbPlayMonoSingleCycle    NEAR
  972.  
  973.     SBCMD    0D1h            ; turn on DAC speaker
  974.     SBCMD    40h            ; set Transfer Time Constant
  975.         SBCMD   <[byte sbTimeConstant]> ; Time Constant
  976.     SBCMD    14h            ; 8-bit PCM output
  977.     SBCMD    <[byte sbBlockLength]>      ; block length low byte
  978.     SBCMD    <[byte sbBlockLength+1]>  ; block length high byte
  979.  
  980. @@err:
  981.     ret
  982. ENDP
  983.  
  984.  
  985.  
  986.  
  987. ;/***************************************************************************\
  988. ;*
  989. ;* Function:    sbSingleCycleIRQ
  990. ;*
  991. ;* Description: SB DSP interrupt service routine for 8-bit Single-Cycle mode
  992. ;*
  993. ;\***************************************************************************/
  994.  
  995. PROC NOLANGUAGE sbSingleCycleIRQ
  996.  
  997.     sti
  998.         push    _ax
  999.         push    _cx
  1000.         push    _dx                     ; save all registers that will be
  1001.     push    ds            ; changed
  1002.  
  1003.         ; FIXME:
  1004.         mov     ax,DGROUP
  1005.     mov    ds,ax
  1006.  
  1007.     SBCMD    14h            ; 8-bit PCM output
  1008.     SBCMD    <[byte sbBlockLength]>      ; block length low byte
  1009.     SBCMD    <[byte sbBlockLength+1]>  ; block length high byte
  1010.  
  1011. @@err:    ; no error handling can be done here
  1012.  
  1013.         mov     _dx,[SB.port]
  1014.         add     _dx,0Eh                 ; acknowledge DSP interrupt
  1015.     in    al,dx
  1016.  
  1017.     cmp    [SB.IRQ],7
  1018.     ja    @@upirq
  1019.  
  1020.     mov    al,20h            ; send End Of Interrupt command to
  1021.     out    20h,al            ; PIC
  1022.     jmp    @@done
  1023.  
  1024. @@upirq:
  1025.     mov    al,20h            ; send EOI to PIC #2 (IRQ > 7)
  1026.     out    0A0h,al
  1027.         out     20h,al
  1028.  
  1029. @@done:
  1030.     pop    ds
  1031.         pop     _dx
  1032.         pop     _cx
  1033.         pop     _ax
  1034.  
  1035. IFDEF __16__
  1036.         iret                            ; some TASM versions seem to generate
  1037. ELSE                                    ; iret even in 32-bit modes
  1038.         iretd
  1039. ENDIF
  1040. ENDP
  1041.  
  1042.  
  1043.  
  1044.  
  1045. ;/***************************************************************************\
  1046. ;*
  1047. ;* Function:    sbPlayMonoAutoinit
  1048. ;*
  1049. ;* Description: Starts playing the buffer using 8-bit Auto-initialize mode
  1050. ;*
  1051. ;\***************************************************************************/
  1052.  
  1053. PROC NOLANGUAGE sbPlayMonoAutoinit    NEAR
  1054.  
  1055.     SBCMD    0D1h            ; turn on DAC speaker
  1056.     SBCMD    40h            ; set DSP Transfer Time Constant
  1057.         SBCMD   <[byte sbTimeConstant]> ; Transfer Time Constant
  1058.     SBCMD    48h            ; set DSP transfer block size
  1059.     SBCMD    <[byte sbBlockLength]>      ; block length low byte
  1060.     SBCMD    <[byte sbBlockLength+1]>  ; block length high byte
  1061.     SBCMD    1Ch            ; start 8-bit PCM output
  1062.  
  1063. @@err:
  1064.     ret
  1065. ENDP
  1066.  
  1067.  
  1068.  
  1069.  
  1070. ;/***************************************************************************\
  1071. ;*
  1072. ;* Function:    sbAutoinitIRQ
  1073. ;*
  1074. ;* Description: SB DSP interrupt service routine for 8-bit Auto-initialize
  1075. ;*        mode
  1076. ;*
  1077. ;\***************************************************************************/
  1078.  
  1079. PROC NOLANGUAGE sbAutoinitIRQ
  1080.  
  1081.     sti
  1082.         push    _ax
  1083.         push    _cx
  1084.         push    _dx                     ; save all registers that will be
  1085.         push    ds                      ; changed
  1086.  
  1087.         ; Fixme:
  1088.         mov     ax,DGROUP
  1089.     mov    ds,ax
  1090.  
  1091.     test    [sbMode],sd16bit    ; 16-bit output mode?
  1092.     jnz    @@16
  1093.  
  1094.         mov     _dx,[SB.port]
  1095.         add     _dx,0Eh                 ; acknowledge DSP interrupt
  1096.     in    al,dx
  1097.     jmp    @@ackdone
  1098.  
  1099. @@16:
  1100.         mov     _dx,[SB.port]
  1101.         add     _dx,0Fh                 ; acknowledge DSP interrupt
  1102.     in    al,dx
  1103.  
  1104. @@ackdone:
  1105.     cmp    [SB.IRQ],7
  1106.     ja    @@upirq
  1107.  
  1108.     mov    al,20h            ; send End Of Interrupt command to
  1109.     out    20h,al            ; PIC
  1110.     jmp    @@done
  1111.  
  1112. @@upirq:
  1113.     mov    al,20h            ; send EOI to PIC #2 (IRQ > 7)
  1114.     out    0A0h,al
  1115.         out     20h,al
  1116.  
  1117. @@done:
  1118.     pop    ds
  1119.         pop     _dx
  1120.         pop     _cx
  1121.         pop     _ax
  1122.  
  1123. IFDEF __16__
  1124.         iret                            ; some TASM versions seem to generate
  1125. ELSE                                    ; iret even in 32-bit modes
  1126.         iretd
  1127. ENDIF
  1128. ENDP
  1129.  
  1130.  
  1131.  
  1132.  
  1133. ;/***************************************************************************\
  1134. ;*
  1135. ;* Function:    sbPlayMonoHighSpeed
  1136. ;*
  1137. ;* Description: Starts playing the buffer using 8-bit mono High-Speed
  1138. ;*        Auto-initialize mode
  1139. ;*
  1140. ;\***************************************************************************/
  1141.  
  1142. PROC NOLANGUAGE sbPlayMonoHighSpeed    NEAR
  1143.  
  1144.     SBCMD    0D1h            ; turn on DAC speaker
  1145.     SBCMD    40h            ; set DSP transfer Time Constant
  1146.         SBCMD   <[byte sbTimeConstant]> ; transfer Time Constant
  1147.     SBCMD    48h            ; set DSP transfer block size
  1148.     SBCMD    <[byte sbBlockLength]>      ; block length low byte
  1149.     SBCMD    <[byte sbBlockLength+1]>  ; block length high byte
  1150.     SBCMD    90h            ; 8-bit PCM high-speed output
  1151.  
  1152. @@err:
  1153.     ret
  1154. ENDP
  1155.  
  1156.  
  1157.  
  1158.  
  1159. ;/***************************************************************************\
  1160. ;*
  1161. ;* Function:    sbSetStereo
  1162. ;*
  1163. ;* Description: Sets the SB hardware to stereo mode and plays a single
  1164. ;*        silent byte. Called before starting stereo transfer on
  1165. ;*        DSP < 4.00 to make sure that the channels are the right
  1166. ;*        way and not reversed (left comes from left and right from
  1167. ;*              right). Note that this is not of our own invention, but is
  1168. ;*              actually documented in the SDK.
  1169. ;*
  1170. ;\***************************************************************************/
  1171.  
  1172. PROC NOLANGUAGE sbSetStereo    NEAR
  1173.  
  1174.     SBCMD    0D1h
  1175.  
  1176.         mov     _dx,[SB.port]
  1177.         add     _dx,04h
  1178.     mov    al,0Eh
  1179.     out    dx,al            ; set the mixer to stereo mode
  1180.         inc     _dx
  1181.     in    al,dx
  1182.     or    al,2
  1183.     out    dx,al
  1184.  
  1185.         ; set up the IRQ handler for transfer:
  1186.         push    ds
  1187.     mov    ah,25h
  1188.         mov     al,[byte sbInterrupt]
  1189.         mov     dx,cs
  1190.     mov    ds,dx
  1191.         mov     _dx,offset @@irqhandler
  1192.     int    21h
  1193.     pop    ds
  1194.  
  1195.         ; Set up the DMA buffer for one byte transfer:
  1196.         mov     [sbStereoDMABuffer.startAddr],0
  1197.         mov     [sbStereoDMABuffer.bufferLen],0
  1198.         mov     [sbStereoDMABuffer.channel],-1
  1199.  
  1200.         ; program the DMA controller for single-cycle output:
  1201. IFDEF __16__
  1202.         call    dmaPlayBuffer LANG, \
  1203.                 seg sbStereoDMABuffer offset sbStereoDMABuffer, [SB.DMA], 0
  1204. ELSE
  1205.         push    es
  1206.         call    dmaPlayBuffer LANG, offset sbStereoDMABuffer, [SB.DMA], 0
  1207.         pop     es
  1208. ENDIF
  1209.         test    _ax,_ax
  1210.     jnz    @@err
  1211.  
  1212.     mov    [sbStereoOK],0
  1213.  
  1214.     SBCMD    14h
  1215.     SBCMD    0            ; program the DSP to output one
  1216.     SBCMD    0            ; silent byte (80h)
  1217.  
  1218.     ; wait until the IRQ occurs:
  1219. @@w:
  1220.     cmp    [sbStereoOK],1
  1221.     jne    @@w
  1222.  
  1223.         xor     _ax,_ax
  1224.  
  1225. @@err:
  1226.     ret
  1227.  
  1228.  
  1229. @@irqhandler:
  1230.     ; IRQ handler routine:
  1231.  
  1232.         push    _ax
  1233.         push    _cx
  1234.         push    _dx                     ; save all registers that will be
  1235.     push    ds            ; changed
  1236.  
  1237.         ; FIXME:
  1238.         mov     ax,DGROUP
  1239.     mov    ds,ax
  1240.  
  1241.     mov    [sbStereoOK],1        ; set interrupt flag
  1242.  
  1243.         mov     _dx,[SB.port]
  1244.         add     _dx,0Eh                 ; acknowledge DSP interrupt
  1245.     in    al,dx
  1246.  
  1247.     cmp    [SB.IRQ],7
  1248.     ja    @@upirq
  1249.  
  1250.     mov    al,20h            ; send End Of Interrupt command to
  1251.     out    20h,al            ; PIC
  1252.     jmp    @@done
  1253.  
  1254. @@upirq:
  1255.     mov    al,20h            ; send EOI to PIC #2 (IRQ > 7)
  1256.     out    0A0h,al
  1257.         out     020h,al
  1258.  
  1259. @@done:
  1260.     pop    ds
  1261.         pop     _dx
  1262.         pop     _cx
  1263.         pop     _ax
  1264.  
  1265. IFDEF __16__
  1266.     iret
  1267. ELSE
  1268.         iretd
  1269. ENDIF
  1270. ENDP
  1271.  
  1272.  
  1273.  
  1274.  
  1275. ;/***************************************************************************\
  1276. ;*
  1277. ;* Function:    sbPlayStereo
  1278. ;*
  1279. ;* Description: Starts playing the buffer using 8-bit stereo High-Speed
  1280. ;*        Auto-initialize mode
  1281. ;*
  1282. ;\***************************************************************************/
  1283.  
  1284. PROC NOLANGUAGE sbPlayStereo    NEAR
  1285.  
  1286.     SBCMD    0D1h            ; turn on DAC speaker
  1287.     SBCMD    40h            ; set DSP transfer Time Constant
  1288.         SBCMD   <[byte sbTimeConstant]> ; transfer Time Constant
  1289.  
  1290.     ; save output filter status and turn it off:
  1291.         mov     _dx,[SB.port]
  1292.         add     _dx,04h
  1293.     mov    al,0Ch
  1294.     out    dx,al
  1295.         inc     _dx
  1296.     in    al,dx
  1297.         mov     [sbOutputFilter],al
  1298.     or    al,20h
  1299.     out    dx,al
  1300.  
  1301.     SBCMD    48h            ; set DSP transfer block size
  1302.     SBCMD    <[byte sbBlockLength]>      ; block length low byte
  1303.     SBCMD    <[byte sbBlockLength+1]>  ; block length high byte
  1304.     SBCMD    90h            ; 8-bit PCM high-speed output
  1305.  
  1306. @@err:
  1307.     ret
  1308. ENDP
  1309.  
  1310.  
  1311.  
  1312.  
  1313. ;/***************************************************************************\
  1314. ;*
  1315. ;* Function:    sbPlay400
  1316. ;*
  1317. ;* Description: Starts playing the buffer using the DSP 4.00 Auto-initialize
  1318. ;*        transfer
  1319. ;*
  1320. ;\***************************************************************************/
  1321.  
  1322. PROC NOLANGUAGE sbPlay400    NEAR
  1323.  
  1324.     SBCMD    41h            ; set DSP output sampling rate
  1325.     SBCMD    <[byte sbRate+1]>    ; sampling rate high byte
  1326.     SBCMD    <[byte sbRate]>     ; sampling rate low byte
  1327.  
  1328.     test    [sbMode],sd8bit     ; 8-bit mode?
  1329.     jnz    @@8bit
  1330.  
  1331.     SBCMD    0B4h            ; 16-bit output
  1332.     test    [sbMode],sdMono     ; mono?
  1333.     jnz    @@mono16
  1334.     SBCMD    30h            ; 16-bit stereo signed PCM
  1335.     jmp    @@setlen
  1336. @@mono16:
  1337.     SBCMD    10h            ; 16-bit mono signed PCM
  1338.     jmp    @@setlen
  1339.  
  1340. @@8bit:
  1341.     SBCMD    0C6h            ; 8-bit output
  1342.     test    [sbMode],sdMono     ; mono?
  1343.     jnz    @@mono8
  1344.     SBCMD    20h            ; 8-bit stereo unsigned PCM
  1345.     jmp    @@setlen
  1346. @@mono8:
  1347.     SBCMD    00h            ; 8-bit mono unsigned PCM
  1348.  
  1349. @@setlen:
  1350.     SBCMD    <[byte sbBlockLength]>      ; transfer length low byte
  1351.     SBCMD    <[byte sbBlockLength+1]>  ; transfer length high byte
  1352.  
  1353. @@err:
  1354.     ret
  1355. ENDP
  1356.  
  1357.  
  1358.  
  1359.  
  1360. ;/***************************************************************************\
  1361. ;*
  1362. ;* Function:    int sbClose(void)
  1363. ;*
  1364. ;* Description: Uninitializes Sound Blaster
  1365. ;*
  1366. ;* Returns:    MIDAS error code
  1367. ;*
  1368. ;\***************************************************************************/
  1369.  
  1370. PROC    sbClose         _funct
  1371. USES    _bx
  1372.  
  1373.     ; Reset DSP _twice_ to stop playing and reset it: (In High-Speed mode
  1374.     ; the first DSP reset just stops the playing. Besides, this should
  1375.         ; not hurt anyone in any output mode anyway.)
  1376.         mov     _bx,2
  1377.         mov     _dx,[SB.port]
  1378.         add     _dx,06h
  1379.  
  1380. @@reset:
  1381.     mov    al,1            ; reset SB DSP by first writing 1 to
  1382.     out    dx,al            ; port 2x6h
  1383.         mov     _cx,SB_RESETDELAY
  1384. @@delay:
  1385.     in    al,dx            ; wait for a while (3 usecs)
  1386.     loop    @@delay
  1387.     xor    al,al            ; and write 0 to port 2x6h
  1388.         out     dx,al
  1389.  
  1390.         mov     _cx,SB_RESETDELAY
  1391. @@delay2:                ; another delay
  1392.     in    al,dx
  1393.     loop    @@delay2
  1394.  
  1395.         dec     _bx                     ; and reset again
  1396.     jnz    @@reset
  1397.  
  1398.  
  1399.         ; Take care of common uninitialization for all mixing Sound Devices:
  1400.         push    es
  1401.         call    mixsdClose
  1402.         pop     es
  1403.         test    _ax,_ax
  1404.         jnz     @@err
  1405.  
  1406.  
  1407.         cmp     [SB.IRQ],7              ; is IRQ number > 7 ?
  1408.     ja    @@i8
  1409.  
  1410.         mov     al,[oldIRQMask]
  1411.     out    21h,al            ; restore old IRQ mask, IRQ <= 7
  1412.     jmp    @@ivect
  1413.  
  1414. @@i8:   mov     al,[oldIRQMask]         ; restore old IRQ mask, IRQ > 7
  1415.     out    0A1h,al
  1416.  
  1417. @@ivect:
  1418.     push    ds
  1419.         mov     al,[byte sbInterrupt]
  1420.     mov    ah,25h            ; restore old IRQ vector
  1421.         lds     _dx,[oldIRQ]
  1422.     int    21h
  1423.     pop    ds
  1424.  
  1425.         SBCMD   0D3h                    ; turn off the DAC speaker
  1426.  
  1427.     cmp    [SB.cardType],sbPro
  1428.     jne    @@stok            ; using stereo on SB Pro?
  1429.     test    [sbMode],sdStereo
  1430.     jz    @@stok
  1431.  
  1432.     ; stereo on SB Pro - restore the output filter status and set
  1433.     ; hardware to mono mode:
  1434.  
  1435.         mov     _dx,[SB.port]
  1436.         add     _dx,04h                 ; write 04h to port 2x4h
  1437.     mov    al,0Ch
  1438.     out    dx,al
  1439.         inc     _dx
  1440.     mov    al,[sbOutputFilter]    ; write output filter value to 2x5h
  1441.     out    dx,al
  1442.  
  1443.         dec     _dx
  1444.     mov    al,0Eh
  1445.     out    dx,al
  1446.         inc     _dx                     ; turn off stereo mode
  1447.     in    al,dx
  1448.     and    al,not 02h
  1449.     out    dx,al
  1450.  
  1451. @@stok:
  1452.         xor     _ax,_ax
  1453.     jmp    @@done
  1454.  
  1455. @@err:    ERROR    ID_sbClose
  1456.  
  1457. @@done:
  1458.     ret
  1459. ENDP
  1460.  
  1461.  
  1462. ;* $Log: sb.asm,v $
  1463. ;* Revision 1.5  1997/01/16 18:41:59  pekangas
  1464. ;* Changed copyright messages to Housemarque
  1465. ;*
  1466. ;* Revision 1.4  1997/01/16 18:27:15  pekangas
  1467. ;* Fixed IRQ acknowledging with IRQs >7 (thanks Statix)
  1468. ;*
  1469. ;* Revision 1.3  1996/10/13 16:55:18  pekangas
  1470. ;* Fixed a bug in detecting IRQs >9
  1471. ;*
  1472. ;* Revision 1.2  1996/08/04 11:33:44  pekangas
  1473. ;* All functions now preserve _bx
  1474. ;*
  1475. ;* Revision 1.1  1996/05/22 20:49:33  pekangas
  1476. ;* Initial revision
  1477. ;*
  1478.  
  1479. END